package simple;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Enumeration;

import javax.comm.CommPortIdentifier;
import javax.comm.PortInUseException;
import javax.comm.SerialPort;
import javax.comm.UnsupportedCommOperationException;

import simple.enums.BaudRate;
import simple.enums.DataBits;
import simple.enums.Parity;
import simple.enums.StopBits;

public class GpsDock {
	
	private GpsUnit unit;
	private ArrayList<IDockListener> dockListeners;
	private ArrayList<IGpsListener> gpsListeners;
	private CommPortIdentifier commPortIdentifier;
	private SerialPort port;
	private InputStream inputStream;
	
	private GpsReader reader;
	
	public GpsDock(){
		dockListeners = new ArrayList<IDockListener>();
		gpsListeners = new ArrayList<IGpsListener>();
	}
	
	public Iterable<CommPortIdentifier> getCommPortIdentifiers(){
		ArrayList<CommPortIdentifier> identifiers = new ArrayList<CommPortIdentifier>();
		Enumeration<?> e = CommPortIdentifier.getPortIdentifiers();
		while (e.hasMoreElements()) {
			CommPortIdentifier commPort = (CommPortIdentifier) e.nextElement();
			// Only include the serial ports that are not currently owned by any software:
			if (commPort.getPortType() == CommPortIdentifier.PORT_SERIAL && !commPort.isCurrentlyOwned()) {
				identifiers.add(commPort);
			}
		}
		return identifiers;
	}
	
	public void openCommPort(CommPortIdentifier commPortIdentifier) throws PortInUseException, UnsupportedCommOperationException, IOException
	{
		this.commPortIdentifier = commPortIdentifier;
		this.port = (SerialPort)commPortIdentifier.open("JSpoorloos", 5000);
		this.port.setSerialPortParams(unit.baudRate.baudRate(), unit.dataBits.getApiCode(), unit.stopBits.getApiCode(), unit.parity.getApiCode());
		
		this.inputStream = this.port.getInputStream();
	}
	
	public OutputStream getOutputStream() throws IOException {
		return this.port.getOutputStream();
	}
	
	public boolean connect(){
		reader = new QstarzReader(inputStream);
		
		for (IGpsListener listener : this.gpsListeners) {
			reader.addGpsListener(listener);
		}
		
		reader.activate();
		return reader.isActive();
	}
	
	public void disconnect(){
		reader.clearGpsListeners();
		reader.deactivate();
		
		this.port.close();
		try {
			this.inputStream.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		this.inputStream = null;
	}
	
	
	
	
	// Plumbing code:
	public void registerDockListener(IDockListener listener){
		dockListeners.add(listener);
	}
	public void deregisterDockListener(IDockListener listener){
		dockListeners.remove(listener);
	}
	public void clearDockListeners(){
		dockListeners.clear();
	}
	
	
	public void addGpsListener(IGpsListener listener){
		this.gpsListeners.add(listener);
	}
	public void removeGpsListener(IGpsListener listener){
		this.gpsListeners.remove(listener);
	}
	public void clearGpsListeners(){
		this.gpsListeners.clear();
	}
	
	// Getters and Setters:
	
	public GpsUnit getUnit() {
		return unit;
	}

	public void setUnit(GpsUnit unit) {
		if (this.unit != unit) {
			this.unit = unit;
			for (IDockListener listener : dockListeners) {
				listener.unitDocked(new DockEvent(unit));
			}
		}
	}
}
